﻿using Framework.Core.Attributes;
using Framework.Core.Consts;
using Framework.Core.Enums;
using Framework.Core.Helper;
using my.abp.Domain.IManagers.Org;
using my.abp.Domain.IManagers.User;
using my.abp.Domain.Repositories.User;
using my.abp.Domain.Shared.Entities;
using my.abp.Domain.Shared.Enums;
using SqlSugar;
using Volo.Abp;
using Volo.Abp.Caching;
using Volo.Abp.Domain.Services;
using Volo.Abp.Uow;

namespace my.abp.Domain.Managers.User
{
	public class SysUserManager : DomainService, ISysUserManager
	{
		private readonly ISysUserRepository _sysUserRepository;
		private readonly ISysOrgManager _sysOrgManager;
		private readonly ISysUserRoleManager _sysUserRoleManager;
		private readonly ISysUserExtOrgManager _sysUserExtOrgManager;
		private Framework.AspNetCore.User.CurrentUser _CurrentUser;
		private readonly IDistributedCache<object, string> _sysCacheService;

		public SysUserManager(ISysUserRepository sysUserRepository, ISysOrgManager sysOrgManager, 
			ISysUserRoleManager sysUserRoleManager, ISysUserExtOrgManager sysUserExtOrgManager,
			IDistributedCache<object, string> sysCacheService, Framework.AspNetCore.User.CurrentUser currentUser)
		{
			_sysUserRepository = sysUserRepository;
			_sysOrgManager = sysOrgManager;
			_sysUserRoleManager = sysUserRoleManager;
			_sysUserExtOrgManager = sysUserExtOrgManager;
			_CurrentUser = currentUser;
			_sysCacheService = sysCacheService;
		}

		/// <summary>
		/// 获取用户分页列表
		/// </summary>
		/// <param name="Name"></param>
		/// <param name="Account"></param>
		/// <param name="OrgId"></param>
		/// <param name="pageNumber"></param>
		/// <param name="pageSize"></param>
		/// <param name="total"></param>
		/// <returns></returns>
		public async Task<List<SysUser>> ListAsync(string Name, string Account, long OrgId, int pageNumber, int pageSize, RefAsync<int> total)
		{
			var userOrgIdList = await _sysOrgManager.GetUserOrgIdList();
			List<long> orgList = null;
			if (OrgId > 0)  // 指定机构查询时
			{
				orgList = await _sysOrgManager.GetChildIdListWithSelfById(OrgId);
				orgList = _CurrentUser.SuperAdmin ? orgList : orgList.Where(u => userOrgIdList.Contains(u)).ToList();
			}
			else // 各管理员只能看到自己机构下的用户列表
			{
				orgList = _CurrentUser.SuperAdmin ? null : userOrgIdList;
			}

			var queryable = await _sysUserRepository.AsQueryable();

			if (queryable == null)
			{
				total = 0;
				return null;
			}

			return await queryable
				//.WhereIF(orgList != null, u => orgList.Contains(u.OrgId))
				.Where(x => x.Name.Contains(Name))
				.WhereIF(orgList != null, u => orgList.Contains(u.OrgId))
				.WhereIF(!string.IsNullOrWhiteSpace(Account), u => u.Account.Contains(Account))
				.WhereIF(!string.IsNullOrWhiteSpace(Name), u => u.Name.Contains(Name))
				.OrderBy(u => u.OrderNo)
				.ToPageListAsync(pageNumber, pageSize, total);

		}

		/// <summary>
		/// 增加用户
		/// </summary>
		/// <param name="user"></param>
		/// <param name="RoleIdList"></param>
		/// <param name="ExtOrgIdList"></param>
		/// <returns></returns>
		/// <exception cref="UserFriendlyException"></exception>
		[UnitOfWork]
		public async Task<long> AddUser(SysUser user, List<long> RoleIdList, List<long> ExtOrgIdList)
		{
			var queryable = await _sysUserRepository.AsQueryable();

			var isExist = await queryable.Filter(null, true).AnyAsync(u => u.Account == user.Account);
			if (isExist) throw new UserFriendlyException("账号已存在！");

			//var password = await _sysConfigService.GetConfigValue<string>(CommonConst.SysPassword);
			var password = "111111";

			MD5Encryption.Encrypt(password, true, false);
			//var user = input.Adapt<SysUser>();
			user.Password = MD5Encryption.Encrypt(password, true, false);
			var insertable = await _sysUserRepository.AsInsertable(user);
			var newUser = await insertable.ExecuteReturnEntityAsync();
			user.Id = newUser.Id;
			await UpdateRoleAndExtOrg(user, RoleIdList, ExtOrgIdList);

			return newUser.Id;
		}

		/// <summary>
		/// 更新角色和扩展机构
		/// </summary>
		/// <param name="input"></param>
		/// <returns></returns>
		private async Task UpdateRoleAndExtOrg(SysUser user, List<long> RoleIdList, List<long> ExtOrgIdList)
		{
			await GrantRole(user.Id, RoleIdList);

			await _sysUserExtOrgManager.UpdateUserExtOrg(user.Id, ExtOrgIdList);
		}

		public async Task<SysUser> GetAsync(string Account)
		{
			return await _sysUserRepository.GetAsync(Account);
		}

		/// <summary>
		/// 授权用户角色
		/// </summary>
		/// <param name="input"></param>
		/// <returns></returns>
		public async Task GrantRole(long UserId, List<long> RoleIdList)
		{
			var user = await _sysUserRepository.GetFirstAsync(u => u.Id == UserId) ?? throw new UserFriendlyException("账号不存在！");
			if (user.Name == CommonConst.SuperAdmin)
				throw new UserFriendlyException("禁止为超级管理员分配角色！");

			await _sysUserRoleManager.GrantUserRole(UserId,RoleIdList);
		}

		/// <summary>
		/// 更新用户
		/// </summary>
		/// <param name="user"></param>
		/// <param name="RoleIdList"></param>
		/// <param name="ExtOrgIdList"></param>
		/// <returns></returns>
		/// <exception cref="UserFriendlyException"></exception>
		[UnitOfWork]
		public async Task UpdateUser(SysUser user, List<long> RoleIdList, List<long> ExtOrgIdList)
		{

			var queryable = await _sysUserRepository.AsQueryable();

			if (await queryable.Filter(null, true).AnyAsync(u => u.Account == user.Account && u.Id != user.Id))
				throw new UserFriendlyException("账号已存在！");

			var updateable = await  _sysUserRepository.AsUpdateable(user);
			await updateable.IgnoreColumns(true)
				.IgnoreColumns(u => new { u.Password, u.Status }).ExecuteCommandAsync();

			await UpdateRoleAndExtOrg(user, RoleIdList, ExtOrgIdList);

			var db = await _sysUserRepository.GetDbContextAsync();
			var ContextID = db.ContextID;

			// 删除用户机构缓存
			DeleteUserOrgCache(user.Id, ContextID.ToString());
		}

		public void DeleteUserOrgCache(long userId, string ContextID)
		{
			_sysCacheService.Remove($"{"sys_user_org:"}{userId}");
			_sysCacheService.Remove($"{"sys_role_maxDataScope:"}{userId}");
			_sysCacheService.Remove($"db:{ContextID}:orgList:{userId}");
		}

		/// <summary>
		/// 删除用户
		/// </summary>
		/// <param name="input"></param>
		/// <param name="RoleIdList"></param>
		/// <param name="ExtOrgIdList"></param>
		/// <returns></returns>
		/// <exception cref="UserFriendlyException"></exception>
		[UnitOfWork]
		public async Task DeleteUser(SysUser input)
		{
			var user = await _sysUserRepository.GetFirstAsync(u => u.Id == input.Id) ?? 
				throw new UserFriendlyException(RemarkAttribute.GetEnumRemark(ErrorCodeEnum.D0009));

			if (user.Name == CommonConst.SuperAdmin)
				throw new UserFriendlyException(RemarkAttribute.GetEnumRemark(ErrorCodeEnum.D1014));
			if (user.Id == _CurrentUser.UserId)
				throw new UserFriendlyException(RemarkAttribute.GetEnumRemark(ErrorCodeEnum.D1001));

			await _sysUserRepository.DeleteAsync(user);

			// 删除用户角色
			await _sysUserRoleManager.DeleteUserRoleByUserId(input.Id);

			// 删除用户扩展机构
			await _sysUserExtOrgManager.DeleteUserExtOrgByUserId(input.Id);
		}

		public async Task<SysUser> GetBaseInfo()
		{
			return await _sysUserRepository.GetFirstAsync(u => u.Id == _CurrentUser.UserId);
		}

		public async Task<int> UpdateBaseInfo(SysUser user)
		{
			var updateable = await _sysUserRepository.AsUpdateable(user);
			return await updateable.IgnoreColumns(u => new { u.CreateTime, u.Account, u.Password, u.OrgId }).ExecuteCommandAsync();
		}

		public async Task<int> SetStatus(long Id, StatusEnum Status)
		{
			
			var user = await _sysUserRepository.GetFirstAsync(u => u.Id == Id) ?? 
				throw new UserFriendlyException(RemarkAttribute.GetEnumRemark(ErrorCodeEnum.D0009));
			if (user.Name == CommonConst.SuperAdmin)
				throw new UserFriendlyException(RemarkAttribute.GetEnumRemark(ErrorCodeEnum.D1015));
			if (!System.Enum.IsDefined(typeof(StatusEnum),Status))
				throw new UserFriendlyException(RemarkAttribute.GetEnumRemark(ErrorCodeEnum.D3005));
			user.Status = Status;

			var updateable = await _sysUserRepository.AsUpdateable(user);
			return await updateable.UpdateColumns(u => new { u.Status }).ExecuteCommandAsync();
		}

		public async Task<int> ChangePwd(string PasswordOld, string PasswordNew)
		{
			var user = await _sysUserRepository.GetFirstAsync(u => u.Id == _CurrentUser.UserId) ??
				throw new UserFriendlyException(RemarkAttribute.GetEnumRemark(ErrorCodeEnum.D0009));
			if (user.Password != MD5Encryption.Encrypt(PasswordOld, true, false))
				throw new UserFriendlyException(RemarkAttribute.GetEnumRemark(ErrorCodeEnum.D1004));

			user.Password = MD5Encryption.Encrypt(PasswordNew, true, false);
			var updateable = await _sysUserRepository.AsUpdateable(user);
			return await updateable.UpdateColumns(u => u.Password).ExecuteCommandAsync();
		}

		/// <summary>
		/// 重置用户密码
		/// </summary>
		/// <param name="Id"></param>
		/// <returns></returns>
		/// <exception cref="UserFriendlyException"></exception>
		public async Task<string> ResetPwd(long Id)
		{
			var user = await _sysUserRepository.GetFirstAsync(u => u.Id == Id) ??
				throw new UserFriendlyException(RemarkAttribute.GetEnumRemark(ErrorCodeEnum.D0009));
			var password = "111111";
			user.Password = MD5Encryption.Encrypt(password, true, false);
			var updateable = await _sysUserRepository.AsUpdateable(user);
			await updateable.UpdateColumns(u => u.Password).ExecuteCommandAsync();
			return password;
		}
	}
}
